package com.autocloud.controller;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.autocloud.model.Result;
import com.autocloud.model.security.Account;
import com.autocloud.model.security.Person;
import com.autocloud.repository.AccountRepository;
import com.autocloud.service.AccountService;
import com.autocloud.util.UuidUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author zhongwb
 * @version 1.0
 * @description
 * @date 2019/12/14 3:13 下午
 */
@RestController
@RequestMapping(value = "/auth")
public class AuthController {

    @Value("${jwt.secret.key}")
    private String secretKey;

    @Value("${token.expire.time}")
    private long tokenExpireTime;

    @Value("${refresh.token.expire.time}")
    private long refreshTokenExpireTime;

    @Value("${jwt.refresh.token.key.format}")
    private String jwtRefreshTokenKeyFormat;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    AccountRepository accountRepository;

    @Resource
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private HttpServletRequest servletRequest;

    @Autowired
    private AccountService accountService;


    @PostMapping("/login")
    public Result<Map<String, Object>> login(@RequestBody Map<String, String> Param) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        String userName = Param.get("username");
        String password = Param.get("password");

        Optional<Account> accountOptional = accountRepository.findByAccount(userName);
        if (!accountOptional.isPresent()) {
            return Result.oflost("账号不存在！", 201);
        }

        Account account = accountOptional.get();
        //判断密码是否正确
        if (!bCryptPasswordEncoder.matches(password, account.getPwd())) {
            return Result.oflost("密码错误！", 201);
        }
        // 生成JWT
        String token = buildJWT(account);
        // 生成refreshToken
        String refreshToken = UuidUtil.get32Uuid();
        // 保存refreshToken至redis，使用hash结构保存使用中的token以及用户标识
        String refreshTokenKey = String.format(jwtRefreshTokenKeyFormat, refreshToken);
        stringRedisTemplate.opsForHash().put(refreshTokenKey, "token", token);
        stringRedisTemplate.opsForHash().put(refreshTokenKey, "userName", account.getId());
        // refreshToken设置过期时间
        stringRedisTemplate.expire(refreshTokenKey, refreshTokenExpireTime, TimeUnit.MILLISECONDS);

        // 返回结果
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("token", token);
        dataMap.put("refreshToken", refreshToken);
        dataMap.put("name", account.getTitle());
        dataMap.put("id", account.getId());
        return Result.ofsuccess(dataMap);

    }

    /**
     * 获取用户基本信息
     * @param
     * @return
     */
    @GetMapping("/getUserInfo")
    public Result<Map<String, Object>> getUserInfo() {
        String accountId = servletRequest.getHeader("Authorization-account");
        Optional<Person> personResult = accountRepository.findByAccountId(accountId);
        if(!personResult.isPresent()){
            return Result.oflost("获取用户信息失败！", 210);
        }
        Person person = personResult.get();
        // 返回结果
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("data",person);
        return Result.ofsuccess(dataMap);
    }

    /**
     * 修改用户基本信息
     * @param param
     * @return
     */
    @PostMapping("/updateUserInfo")
    public Result<Map<String, Object>> updateUserInfo(@RequestBody Map<String, String> param) {
        String accountId = servletRequest.getHeader("Authorization-account");
        boolean isSuccess = accountService.updateUserInfo(param,accountId);
        if(!isSuccess){
            return Result.oflost("修改失败！",211);
        }
        // 返回结果
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("success",true);
        return Result.ofsuccess(dataMap);
    }


    /**
     * 修改用户密码
     * @param param
     * @return
     */
    @PostMapping("/newPassword")
    public Result<Map<String, Object>> newPassword(@RequestBody Map<String, String> param) {
        String accountId = servletRequest.getHeader("Authorization-account");
        boolean isSuccess = accountService.newPassword(param,accountId);
        // 返回结果
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("data",isSuccess);
        return Result.ofsuccess(dataMap);
    }


    private String buildJWT(Account account) {
        //生成jwt
        Date now = new Date();
        Algorithm algo = Algorithm.HMAC256(secretKey);
        String token = JWT.create()
                .withIssuer("devloper-platform")
                .withIssuedAt(now)
                .withExpiresAt(new Date(now.getTime() + tokenExpireTime))
                .withClaim("account", account.getId())//保存身份标识
                .withClaim("orgunit", account.getOrganization())
                .withClaim("person", account.getPerson())
                .withClaim("station", account.getStation())
                .sign(algo);
        return token;
    }

}
